﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Media;

namespace Red.Toolkit.Profiler.Logic
{
    /// <summary>
    /// Set of events having the same level (depth) value.
    /// All events on the same level should not overlap.
    /// </summary>
    public class GroupLevel
    {
        // TODO encapsulate
        public SortedDictionary<double, Event> events;
        private EventNode _rootNode;
        private int _levelNumber;

        public GroupLevel( int levelNumber )
        {
            events = new SortedDictionary<double, Event>();
            _rootNode = null;
            this._levelNumber = levelNumber;
        }

        public void BuildTree()
        {
            if ( events.Count == 0 )
            {
                _rootNode = null;
                return;
            }

            EventNode[] prevLayer = new EventNode[events.Count];

            // build bottom layer (leaves)
            double prevEnd = 0.0;
            int id = 0;
            int overlapping = 0;
            foreach ( var p in events )
            {
                if ( p.Value.Evt.StartTime < prevEnd )
                    overlapping++;

                Event e = p.Value;
                prevLayer[id++] = new EventNode( e );
                prevEnd = p.Value.Evt.EndTime;
            }

            if ( overlapping > 0 )
            {
                // TODO of which group?
                Debug.Write( "Warning: " + overlapping + " overlapping events found in level " + _levelNumber );
            }

            EventNode[] newLayer = prevLayer;
            while ( prevLayer.Length > 1 )
            {
                bool odd = prevLayer.Length % 2 == 1;
                int newLayerCount = prevLayer.Length / 2;
                if ( odd )
                    newLayerCount++;

                newLayer = new EventNode[newLayerCount];
                for ( int i = 0; i < prevLayer.Length / 2; ++i )
                    newLayer[i] = new EventNode( prevLayer[2 * i], prevLayer[2 * i + 1] );

                if ( odd )
                    newLayer[prevLayer.Length / 2] = prevLayer[prevLayer.Length - 1];

                prevLayer = newLayer;
            }

            _rootNode = newLayer[0];
        }

        public void UpdateSelection()
        {
            if ( _rootNode != null )
                _rootNode.UpdateSelectionRecursive();
        }

        public EventNode RootNode { get { return _rootNode; } }
    }
}
